package com.hd.zx.qt.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.hd.zx.qt.batch.proccess.UserItemProcessor;
import com.hd.zx.qt.batch.writer.UserWriter;
import com.hd.zx.qt.job.QuartzJobLauncher;
import com.hd.zx.qt.mapper.UserFieldSetMapper;
import com.hd.zx.qt.pojo.User;
import org.quartz.JobDataMap;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.configuration.support.MapJobRegistry;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;

/**
 * <h3>partitionjob</h3>
 * <p>QuartzConfig</p>
 * https://gitee.com/hongdu_dudua1/spring_quartz_mq.git
 * @author : hduong
 * @version : 1.0
 * @date : 2020-09-07 17:50
 **/
@Configuration
public class QuartzConfig {

    @Bean
    public DelimitedLineTokenizer lineTokenizer() {
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        String names = "id,name,age";
        tokenizer.setNames(names);
        return tokenizer;
    }

    @Bean
    public UserFieldSetMapper userFieldSetMapper() {
        return new UserFieldSetMapper();
    }

    @Bean
    public DefaultLineMapper lineMapper() {
        DefaultLineMapper defaultLineMapper = new DefaultLineMapper();
        defaultLineMapper.setLineTokenizer(lineTokenizer());
        defaultLineMapper.setFieldSetMapper(userFieldSetMapper());
        return defaultLineMapper;
    }
//
//     <!--核心业务处理-->
//    <bean id="process" class="com.mlsama.hellospringbatch.config.apart.UserItemProcessor"></bean>
//    <!--持久化处理-->
//    <bean id="write" class="com.mlsama.hellospringbatch.config.apart.UserWriter"></bean>

    @Bean
    public FlatFileItemReader<User> flatfileReader() {
        FlatFileItemReader reader = new FlatFileItemReader();
        reader.setLineMapper(lineMapper());
        ClassPathResource classPathResource = new ClassPathResource("classpath:user.txt");
        reader.setResource(classPathResource);
        reader.setLinesToSkip(10);
        reader.setStrict(false);
        return reader;
    }

    @Bean
    public UserItemProcessor userItemProcessor() {
        return new UserItemProcessor();
    }

    @Bean
    public UserWriter userWriter() {
        return new UserWriter();
    }



    @Bean
    public JobBuilderFactory jobBuilderFactory() throws Exception {
        return new JobBuilderFactory(jorepository());
    }

    @Bean
    public StepBuilderFactory stepBuilderFactory() throws Exception {
        return new StepBuilderFactory(jorepository(), transactionManager());
    }


    @Bean
    public Job jobExample() throws Exception {
        return jobBuilderFactory().get("exampleJob")
                .incrementer(new RunIdIncrementer())
                .start(stepExample())
                .build();
    }

    @Bean
    public Step stepExample() throws Exception {
        return stepBuilderFactory().get("exampleStep")
                .<User, User>chunk(2)
                .reader(flatfileReader())
                .processor(userItemProcessor())
                .writer(userWriter())
                .build();

    }

//     <!-- 配置spring batch的jobRepository，负责与数据库打交道 -->

    @Bean
    public JobRepository jorepository() throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource());
        jobRepositoryFactoryBean.setTransactionManager(transactionManager());
        jobRepositoryFactoryBean.setDatabaseType("MySQL");
        return jobRepositoryFactoryBean.getObject();
    }

    @Bean
    public ResourcelessTransactionManager transactionManager() {
        return new ResourcelessTransactionManager();
    }

    //****job 执行器
    @Bean
    public SimpleAsyncTaskExecutor simpleAsyncTaskExecutor() {
        return new SimpleAsyncTaskExecutor();
    }

    @Bean
    public SimpleJobLauncher jobLauncher() throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jorepository());
        jobLauncher.setTaskExecutor(simpleAsyncTaskExecutor());
        return jobLauncher;
    }

    @Bean
    public MapJobRegistry mapJobRegistry() {
        return new MapJobRegistry();
    }

    /**
     *
     * @return
     */
    @Bean
    public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() {
        JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
        jobRegistryBeanPostProcessor.setJobRegistry(mapJobRegistry());
        return jobRegistryBeanPostProcessor;
    }

    @Bean
    public JobDetailFactoryBean jobDetailFactoryBean() throws Exception {
        JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("job", jobExample());
        jobDataMap.put("jobLauncher", jobLauncher());
        jobDetailFactoryBean.setJobDataMap(jobDataMap);
        jobDetailFactoryBean.setJobClass(QuartzJobLauncher.class);
        return jobDetailFactoryBean;
    }

    @Bean
    @ConfigurationProperties(prefix = "db")
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        return dataSource;
    }

    @Bean
    public JobExplorerFactoryBean jobExplorerFactoryBean() {
        JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
        jobExplorerFactoryBean.setDataSource(dataSource());
        return jobExplorerFactoryBean;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws Exception {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setTriggers(cronTriggerFactoryBean().getObject());
        return schedulerFactoryBean;
    }

    @Bean
    public CronTriggerFactoryBean cronTriggerFactoryBean() throws Exception {
        CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean();
        triggerFactoryBean.setJobDetail(jobDetailFactoryBean().getObject());
        triggerFactoryBean.setCronExpression("0/3 * * * * ?");
        return triggerFactoryBean;
    }


}
